<?php

/*
 * CopyRight  : (C)2012-2099 HaoTeam Inc.
 * Document   : AdminService.php
 * Created on : 2020-10-23 17:44:18
 * Author     : Tiger <1192851302@qq.com>
 * Description: This is NOT a freeware, use is subject to license terms.
 *              这即使是一个免费软件,使用时也请遵守许可证条款,得到当时人书面许可.
 *              未经书面许可,不得翻版,翻版必究;版权归属 HaoTeam Inc;
 */

namespace haoteam\service;

/**
 * 后台管理服务
 * Class AdminService
 * Tiger <1192851302@qq.com> 2020-10-23 17:44:18
 */
class AdminService {

    public static $cache;

    /**
     * 快速实例化模型
     * @param bool $singleton 是否单例
     * @return static
     */
    public static function instance($singleton = true) {
        $name = static::class;
        self::$cache = SessionService::instance()->online_data;
        if (isset($GLOBALS['model'][$name]) and is_object($GLOBALS['model'][$name]) and $singleton) {
            return $GLOBALS['model'][$name];
        } else {
            $GLOBALS['model'][$name] = new static();
            return $GLOBALS['model'][$name];
        }
    }

    /**
     * 主要做兼容日志
     * @return type
     */
    public function getUserId() {
        return self::$cache['user']['id'] ?? 0;
    }

    /**
     * 主要做兼容日志
     * @return type
     */
    public function getUsername() {
        return self::$cache['user']['username'] ?? 0;
    }

    public function isSuper() {
        return self::$cache['user']['roles'] == 1;
    }

    /**
     * 检查指定节点授权
     * --- 需要读取缓存或扫描所有节点
     * @param null|string $node
     * @return boolean
     * @throws \ReflectionException
     * @throws \think\Exception
     */
    public function check(?string $node = '', bool $exception = false): bool {
        if ($this->isSuper()) {
            return true;
        }
        $service = NodeService::instance();
        [$real, $nodes] = [$service->fullnode($node), $service->getMethods()];
        // 以下代码为兼容 win 控制器不区分大小写的验证问题
        foreach ($nodes as $key => $rule) {
            if (strpos($key, '_') !== false && strpos($key, '/') !== false) {
                $attr = explode('/', $key);
                $attr[1] = strtr($attr[1], ['_' => '']);
                $nodes[join('/', $attr)] = $rule;
            }
        }

        if (!empty($nodes[$real]['isauth'])) {
            if (in_array($real, self::$cache['nodes'] ?? []) == false && $exception == true) {
                exception('你没有(' . $nodes[$real]['title'] . ')权限', 410004);
            }
            return in_array($real, self::$cache['nodes'] ?? []);
        }
        if (!empty($nodes[$real]['islogin'])) {
            if (($nodes[$real]['islogin'] && request()->isLogin()) == false && $exception == true) {
                exception('你好像没有登录', 410000);
            }
            return ($nodes[$real]['islogin'] && request()->isLogin());
        }
        return true;
    }

    /**
     * 获取授权节点列表
     * @param array $checkeds
     * @return array
     * @throws \ReflectionException
     */
    public function getTree(array $checkeds = []): array {
        [$nodes, $pnodes, $methods] = [[], [], array_reverse(NodeService::instance()->getMethods(true))];
        foreach ($methods as $node => $method) {
            [$count, $pnode] = [substr_count($node, '/'), substr($node, 0, strripos($node, '/'))];
            //读取当前登陆者的全部权限
            if ($this->isSuper() === false && in_array($node, self::$cache['nodes']) === false) {
                continue;
            }
            if ($count === 2 && !empty($method['isauth'])) {
                in_array($pnode, $pnodes) or array_push($pnodes, $pnode);
                $nodes[$node] = ['spread' => true, 'id' => $node, 'title' => $method['title'], 'pid' => $pnode, 'checked' => in_array($node, $checkeds)];
            } elseif ($count === 1 && in_array($pnode, $pnodes)) {
                $nodes[$node] = ['spread' => true, 'id' => $node, 'title' => $method['title'], 'pid' => $pnode, 'checked' => in_array($node, $checkeds)];
            }
        }
        foreach (array_keys($nodes) as $key) {
            foreach ($methods as $node => $method) {
                if (stripos($key, $node . '/') !== false) {
                    $pnode = substr($node, 0, strripos($node, '/'));
                    $nodes[$node] = ['spread' => true, 'id' => $node, 'title' => $method['title'], 'pid' => $pnode, 'checked' => in_array($node, $checkeds)];
                    $nodes[$pnode] = ['spread' => true, 'id' => $pnode, 'title' => ucfirst($pnode), 'pid' => '', 'checked' => in_array($pnode, $checkeds)];
                }
            }
        }
        return DataExtend::arr2tree(array_reverse($nodes), 'id', 'pid', 'children');
    }

}
